get-the-solution

Checkout dotnet-trace

By
on Regards: C#;

Use dotnet-trace on a sample project

A few days ago, I stumbled upon a video titled Adam Sitnik — Running .NET Core performance investigation on Linux (watch it here). This video showcased the use of common profilers for .NET applications. As someone with a keen interest in program optimization, I was intrigued and decided to experiment with dotnet-trace on a simple project. I was hopeful that the profiler would provide valuable insights for potential optimizations.

Note: The steps outlined below can also be achieved using Visual Studio’s Diagnostic Tools. You can learn more about this here.

Install and setup

Our first order of business is to install dotnet-trace. This can be done with the following command:

dotnet tool install --global dotnet-trace

Next, we need to scrutinize the project settings of the app we wish to profile. Here are a few things to ensure:

  1. the program needs to be run in Release configuration
  2. Make sure the .csproj contains
    <DebugType>pdbonly</DebugType>
    <DebugSymbols>true</DebugSymbols>
    <TieredCompilation>false</TieredCompilation>
  1. I removed or disabled System.Console.WriteLine as it’s a very time consuming method.

Collect data

I’ll profile my recently created ConsoleApp5BoundaryFollowingTracing application to get some new insights. Let’s start one terminal for the app we want to profile and a second terminal on which we collect the profiling information with dotnet trace.

In the first terminal I execute the app with dotnet run ConsoleApp5BoundaryFollowingTracing.csproj -c Release. This process is expected to be a long running task. Otherwise we will not be able to capture the PID and furthermore collect the profiled traces!

Meanwhile we can determine the PID of the app with dotnet trace ps in the second terminal, which lists all currently executed dotnet applications.

dotnet trace ps
      8736 ConsoleApp5BoundaryFollowingTracing [..]\ConsoleApp5BoundaryFollowingTracing.exe
     22356 dotnet     C:\Program Files\dotnet\dotnet.exe
     23488 dotnet     C:\Program Files\dotnet\dotnet.exe
     24008 dotnet     C:\Program Files\dotnet\dotnet.exe

In the next step we start profiling with dotnet trace collect -p 8736. To stop profiling press CTRL+C.

dotnet trace collect -p 8736
No profile or providers specified, defaulting to trace profile 'cpu-sampling'

Provider Name                           Keywords            Level               Enabled By
Microsoft-DotNETCore-SampleProfiler     0x0000F00000000000  Informational(4)    --profile
Microsoft-Windows-DotNETRuntime         0x00000014C14FCCBD  Informational(4)    --profile

Process        : [...]\ConsoleApp5BoundaryFollowingTracing.exe
Output File    : [...]\ConsoleApp5BoundaryFollowingTracing\ConsoleApp5BoundaryFollowingTracing.exe_20220106_123540.nettrace


[00:00:00:03]   Recording trace 1.405    (MB)
Press <Enter> or <Ctrl+C> to exit...
Stopping the trace. This may take several minutes depending on the application being traced.

Trace completed.

Analyse data with speedscope

Under windows you can open the file ConsoleApp5BoundaryFollowingTracing.exe_20220106_123540.nettrace with Visual Studio. An alternative approach is to use the web app speedscope where you can view the profiled information. For this you need to convert the trace file to the speedscope format with:

dotnet trace convert ConsoleApp5BoundaryFollowingTracing.exe_20220106_123540.nettrace --format speedscope

Afterwards start the web app https://www.speedscope.app/ and open the created ConsoleApp5BoundaryFollowingTracing.exe_20220106_123540.speedscope.json file.

At the top you can select the thread you want to investigate. In my case, the relevant data processing happened in the “second” thread. The horizontal timeline can be read from left to right.

(Fig 2. BuildFourierDecriptorsAsync and ReadLine)

From the figure we see that application execution was busy from 0s to about 2.25s with the function BuildFourierDecriptorsAsync. Afterwards System.Console.ReadLine “blocked” the application.

It’s possible to zoom into a specific time range.

(Fig 3. load)

From the graphics (Fig.2 and Fig.3) we can conclude that the app was mostly busy computing the discrete fourier transformation Fourier.Forward(fourier); from MathNet while executing BuildFourierDecriptorsAsync.

Summary

dotnet trace is a good alternative beside Visual Studio for profiling. It can be used to collect the necessary profiler data. For analyzing the data you need external tools like speedscope, etc.

Other profiler tools:

  • Visual Studio
  • PerfCollect
  • VTune

Links: